---
title: Controller 开发
description: 一款企业级 Web 服务开发框架
sidebar:
    order: 4
---
import CheckAuthorize from '../../../components/CheckAuthorize.astro'
import {TabItem, Tabs, Aside} from "@astrojs/starlight/components";

<CheckAuthorize/>

Feat Cloud 在设计 Controller 注解时，一定程度上延用了 Spring 的设计理念，使得用户更容易理解和运用。

当然，我们也并非完全复刻 Spring 的 Controller 注解，而是进行了极致的简化，剔除了不必要的灵活性。

**相关注解：**
- tech.smartboot.feat.cloud.annotation.Controller
- tech.smartboot.feat.cloud.annotation.RequestMapping
- tech.smartboot.feat.cloud.annotation.Param
- tech.smartboot.feat.cloud.annotation.PathParam
- tech.smartboot.feat.cloud.annotation.InterceptorMapping

## 注解详解

### `@Controller`
`@Controller` 用于标记一个类为控制器，作为 Spring 风格的注解设计，降低学习成本。

通常与 `@RequestMapping` 一起使用来定义请求映射路径。

**定义：**
```java
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
@Documented
public @interface Controller {
    String value() default "";
}
```

**value 参数说明：**
- `value()` 定义了 Controller 的基础路径，其他方法级别的请求路径会基于这个基础路径。
- 默认情况下，value 是一个空字符串，意味着没有基础路径前缀。
- 示例：如果设置 `@Controller("/user")`，那么该 Controller 下的所有方法将通过 `/user` 路径前缀访问。

### `@RequestMapping`
`@RequestMapping` 用于标记方法，表示该方法处理特定的 HTTP 请求路径。

支持指定HTTP请求方法，有效类型：`GET`, `HEAD`, `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`, `TRACE`
**定义：**
```java
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
@Documented
public @interface RequestMapping {
    String value() default "";

    RequestMethod[] method() default {};
}
```

**参数说明：**
- **value**: 指定与该方法关联的 URL 路径，默认为空字符串，意味着使用 Controller 级别的路径前缀（如果有）。
- **method**: 指定该方法支持的 HTTP 请求类型，默认不限制请求方法，即所有类型都可以访问该方法。

### `@Param`
`@Param` 用于绑定请求中的查询参数（Query Parameters）到方法参数上。当方法参数为自定义POJO类型时，可无需使用`@Param`注解，框架会自动进行参数绑定。

**定义：**
```java
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.SOURCE)
@Documented
public @interface Param {
    /**
     * 指定要绑定的查询参数的名称。
     *
     * @return 参数名称
     */
    String value();
}
```
**value 参数说明：**
- 如果 HTTP 请求中没有与 `value` 匹配的查询参数，则方法参数将被赋予默认值（如 null、0 或 false，取决于类型）。
- 示例：若方法定义为 `@Param("id") int userId`，则会尝试从请求中获取名为 `id` 的参数并转换为整数赋值给 `userId`。

### `@PathParam`
`@PathParam` 用于绑定请求中的路径参数（Path Parameters）到方法参数上。

**定义：**
```java
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.SOURCE)
@Documented
public @interface PathParam {
    /**
     * 参数名称
     *
     * @return 参数名称
     */
    String value();
}
```

**value 参数说明：** 指定要绑定的路径参数的名称，该名称必须与路由中定义的占位符名称一致。
- 示例：若 URL 定义为 `/user/{id}`，则应使用 `@PathParam("id")` 来绑定路径中的 `id` 值到方法参数。
- 如果 HTTP 请求路径中没有匹配的参数名，则框架会抛出异常或自动赋予默认值（如 null、0 等），具体行为取决于框架实现和参数类型。

### `@InterceptorMapping`
`@InterceptorMapping` 用于为特定的请求路径添加拦截器逻辑，在请求到达目标方法之前执行一些操作。

**定义：**
```java
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
@Documented
public @interface InterceptorMapping {

    String[] value() default "";
}
```

**value 参数说明：** 指定拦截器应用的 URL 路径模式数组。
- 支持精确匹配（如 `/path`）和通配符匹配（如 `/path/*`）。
- 如果未指定，默认为空数组，表示拦截器不匹配任何请求。
- 示例：若设置 `@InterceptorMapping({"/user", "/api/*"})`，则该拦截器会作用于所有 `/user` 和 `/api` 下的请求路径。

## 基本使用

创建一个简单的 Controller 示例：

```java
@Controller("userApi")
public class UserController {
    
    // 支持路径参数
    @RequestMapping("/users/:id")
    public String getUser(@PathParam("id") String id) {
        return "User: " + id;
    }
    
    // 支持查询参数
    @RequestMapping("/users/search")
    public String searchUsers(@Param("name") String name, @Param("age") int age) {
        return "Search users with name: " + name + ", age: " + age;
    }
    
    // 支持对象参数绑定
    @RequestMapping("/users/create")
    public RestResult<Map<String, String>> createUser(UserParam param) {
        RestResult<Map<String, String>> result = new RestResult<>();
        result.setData(Collections.singletonMap("id", "123"));
        return result;
    }
}
```

## 拦截器使用

通过 `@InterceptorMapping` 注解可以为 Controller 添加拦截器，以实现请求的预处理或后处理逻辑。

```java
// 为用户API添加拦截器
@InterceptorMapping({"/users/*"})
public Interceptor userApiInterceptor() {
    return (context, completableFuture, chain) -> {
        System.out.println("Intercepting user API request...");
        // 可以在请求处理前执行前置逻辑
        
        // 继续执行请求链
        chain.proceed(context, completableFuture);
        
        // 可以在请求处理后执行后置逻辑
        System.out.println("Finished intercepting user API request.");
    };
}
```

**说明与注意事项：**
- **拦截路径匹配**：`@InterceptorMapping` 的 `value` 属性用于指定拦截器生效的路径模式，支持精确匹配（如 `/user`）和通配符匹配（如 `/user/*`）。
- **拦截器顺序**：多个拦截器按照定义顺序依次执行，形成拦截器链。
- **异步处理**：由于 HTTP 请求处理可能是异步的，因此拦截器中应正确处理 `CompletableFuture`。
- **避免阻塞**：拦截器中的逻辑不应长时间阻塞主线程，建议将耗时操作提交到独立线程池。
- **异常处理**：拦截器内部需要自行捕获并处理异常，防止因未处理异常导致请求失败。

